use std::{env, process};

use lesson12_1::{Config, run};
fn main() {
    // 1. 获取参数
    // args()返回的是一个迭代器; 
    // 调用迭代器上的collect方法, 返回一个集合
    // 具体什么样的集合无法推断, 所以写上String
    let args:Vec<String> = env::args().collect();
    // 执行cargo run xxx yyy, 下面代码会打印出xxx, yyy这些参数
    // 集合的第一个参数是执行的二进制程序文件的名称
    // println!("{:?}", args);
    // 这样可以分别获取第一第二个参数
    // let query = &args[1];
    // let filename = &args[2];
    // 返回Result类型数据为12.4内容, 表示错误的自定义方式
    // unwrap, 又有将Config将result中解出来之意
    let config = Config::new(&args).unwrap_or_else(|err| {
        // 12.8内容, 将错误信息打印到标准错误输出
        eprintln!("this is err: {}", err);
        process::exit(1)
    });
    println!("query:{:?}; filename:{:?}", config.query, config.filename);
    // 2. 读取文件内容
    // // contents是一个Result类型, 所以可以使用expect
    // let contents = fs::read_to_string(config.filename).expect("出错了大哥!");
    // 12.5内容, 这里又是对Result类型的一种处理
    if let Err(e) = run(config) {
        // 12.8内容, 将错误信息打印到标准错误输出
        // 此时如果在命令行输入cargo run, 会打印出"请输入参数"
        eprintln!("读取阶段出错:{}", e);
        process::exit(1)
    }
    // 12.8改为标准错误输出后, 执行cargo run > output.txt, 那么output.txt中就没有任何数据
    // 而如果是标准输出println!, 那output.txt中就会有错误信息
}



/*
 *dyn Error
dyn关键字是Rust中用于表示动态分派的关键字，它之前的名字是trait关键字（在Rust 2018版之前），但在Rust 2021中推荐使用dyn以提高代码的可读性。dyn用于在运行时确定对象的实际类型，而不是在编译时。
Error是Rust标准库中的一个trait，用于错误处理。任何实现了Error trait的类型都可以被用作错误值。这个trait通常要求实现description方法（在Rust 1.30之后被Display trait取代，但仍可通过std::error::Error的source方法和std::fmt::Display的to_string或fmt方法访问错误信息），用于提供错误的描述。
Box<dyn Error>
Box是Rust中的一个智能指针，用于在堆上分配内存。Box拥有它所指向的值，并在Box被销毁时自动释放该值。这对于动态大小类型（DST）和需要在堆上分配的值特别有用。
Box<dyn Error>因此是一个指向实现了Error trait的值的指针，这个值被分配在堆上。由于Error是一个trait，而Rust的泛型系统不支持直接存储trait实例，因此使用Box和dyn来绕过这个限制，允许我们存储和传递实现了Error trait的值的引用。 
 */
